home *** CD-ROM | disk | FTP | other *** search
- /* Authentication functions - taken from files.c */
- #include "global.h"
- #include "ctype.h"
- #include "commands.h"
- #include "netuser.h"
- #include "files.h"
- #include "md5.h"
- #include "mailbox.h"
-
-
- #if !defined(_lint)
- static char rcsid[] OPTIONAL = "$Id: auth.c,v 1.3 1997/08/19 01:19:22 root Exp root $";
- #endif
-
- extern char Whitespace[];
-
- extern long btol (char *s);
- void usercvt (void);
- char *getsecurity (char *name, int32 *perms);
-
-
- #define lookupBUFSIZ 1024
-
-
- /* Read through FTPUSERS looking for user record
- * Returns line which matches username, or NULLCHAR when no match.
- * Each of the other variables must be copied before freeing the line.
- */
- char *
- userlookup(username,password,directory,permission,ip_address)
- const char *username;
- char **password;
- char **directory;
- long *permission;
- uint32 *ip_address;
- {
- FILE *fp, *fpsave = NULLFILE;
- char *buf;
- char *cp = NULLCHAR;
- int wasanony = 0;
- char *universal = NULLCHAR;
-
- if ((fp = fopen (Userfile, READ_TEXT)) == NULLFILE)
- /* Userfile doesn't exist */
- return NULLCHAR;
-
- buf = mallocw (lookupBUFSIZ);
- for ( ; ; ) {
- if (fgets (buf, lookupBUFSIZ - 1, fp) == NULLCHAR) {
- if (fpsave) {
- (void) fclose (fp);
- fp = fpsave;
- fpsave = NULLFILE;
- continue;
- }
- break;
- }
- if (!strnicmp (buf, "#include", 8)) {
- rip (buf);
- cp = skipwhite (&buf[8]);
- fpsave = fp;
- if((fp = fopen (cp, READ_TEXT)) == NULLFILE) {
- fp = fpsave;
- fpsave = NULLFILE;
- }
- continue;
- }
- if (*buf == '#')
- continue; /* Comment */
-
- if ((cp = strpbrk (buf, " \t")) == NULLCHAR)
- /* Bogus entry */
- continue;
- *cp++ = '\0'; /* Now points to password */
- cp = skipwhite (cp); /* It does now... KFU */
-
- if (stricmp (username, buf) == 0)
- break; /* Found user */
- if (stricmp ("univperm", buf) == 0)
- universal = strdup (cp); /* remember their anon entry */
- }
- if (feof (fp)) {
- if (universal == NULLCHAR) {
- /* username not found in file, nor was univperm */
- if (fpsave)
- (void) fclose (fpsave);
- (void) fclose (fp);
- free (buf);
- return NULLCHAR;
- }
- /* restore anonymous to the buffer */
- strncpy (cp = buf, universal, lookupBUFSIZ);
- wasanony = 1;
- }
- if (universal != NULLCHAR)
- free (universal);
- (void) fclose (fp);
- if (fpsave)
- (void) fclose (fpsave);
-
- if (cp == NULLCHAR)
- return cp;
-
- if (password != NULL)
- *password = cp;
-
- /* Look for space or tab after password field in file */
- if ((cp = strpbrk (cp, " \t")) == NULLCHAR) {
- /* Invalid file entry */
- free (buf);
- return NULLCHAR;
- }
- *cp++ = '\0'; /* Now points to directory field */
- cp = skipwhite (cp);
-
- if (*cp == '#') { /* using a security level entry */
- char *cp2, *path;
- int32 perm = 0;
- rip (cp);
- if ((cp2 = strpbrk (++cp, " \t")) != NULLCHAR)
- *cp2++ = 0;
- path = getsecurity (cp--, &perm);
- if (path != NULLCHAR)
- sprintf(cp, "%s %ld", path, perm);
- }
- if (directory != NULL)
- *directory = cp;
-
- if ((cp = strpbrk (cp, " \t")) == NULLCHAR) {
- /* Permission field missing */
- free (buf);
- return NULLCHAR;
- }
- *cp++ = '\0'; /* now points to permission field */
- cp = skipwhite (cp);
-
- if (permission != NULL) {
- if (!strnicmp (cp, "0x", 2))
- *permission = htol (cp);
- else if (*cp == '%')
- *permission = btol (cp);
- else
- *permission = atol (cp);
- if (wasanony)
- *permission |= WAS_ANONY;
-
- if (*permission & NO_SENDCMD)
- *permission |= (NO_PBBSMAIL + NO_INETMAIL + NO_AMPRMAIL);
-
- }
-
- if ((cp = strpbrk (cp, " \t")) == NULLCHAR) {
- /* IP address missing */
- if (ip_address != NULL)
- *ip_address = 0L;
- } else {
- *cp++ = '\0'; /* now points at IP address field */
- cp = skipwhite (cp);
- if (ip_address != NULL)
- *ip_address = resolve(cp);
- }
- return buf;
- }
-
-
- /* Subroutine for logging in the user whose name is name and password is pass.
- The buffer path should be long enough to keep a line from the userfile.
- If pwdignore is true, the password check will be overridden.
- The return value is the permissions field or -1 if the login failed.
- Path is set to point at the path field, and pwdignore will be true if no
- particular password was needed for this user.
- */
- long
- userlogin(name,pass,path,len,pwdignore)
- const char *name;
- char *pass;
- char **path;
- int len; /* Length of buffer pointed at by *path */
- int *pwdignore;
- {
- char *buf;
- char *password;
- char *directory;
- long permission;
- int anonymous;
- char *cp;
- char hashpass[16];
- MD5_CTX md;
-
- if ((buf = userlookup (name, &password, &directory,
- &permission, NULL)) == NULLCHAR)
- return -1;
-
- anonymous = *pwdignore;
- if (strcmp (password, "*") == 0)
- anonymous = TRUE; /* User ID is password-free */
- if (!anonymous) {
- if (readhex (hashpass, password, sizeof (hashpass)) != (int) sizeof (hashpass)){
- /* Invalid hashed password in file */
- free (buf);
- return -1;
- }
- MD5Init (&md);
- MD5Update (&md, (const unsigned char *) name, strlen (name));
- MD5Update (&md, (unsigned char *) pass, strlen (pass));
- MD5Final (&md);
- if (memcmp (md.digest, hashpass, sizeof (hashpass)) != 0){
- /* Incorrect password given */
- free (buf);
- return -1;
- }
- }
- if ((int)strlen(directory) + 1 > len) {
- /* not enough room for path */
- free (buf);
- return -1;
- }
-
- strncpy (*path, directory, (unsigned) len);
- /* Convert any backslashes to forward slashes, for backward
- * compatibility with the old NET
- */
- while ((cp = strchr (*path, '\\')) != NULLCHAR)
- *cp = '/';
-
- free (buf);
- *pwdignore = anonymous;
- /* Finally return the permission bits */
- return permission;
- }
-
-
- /* MD5 hash plaintext passwords in a file */
- static void
- usercvtfile(const char *file, int recursing)
- {
- FILE *fp,*fptmp;
- char *buf, *cp;
- char hexbuf[16];
- int needsit = 0;
- int len,nlen,plen,i;
- char *pass;
- MD5_CTX md;
-
- if ((fp = fopen (file, READ_TEXT)) == NULLFILE)
- return; /* file doesn't exist */
-
- tprintf ("%sEncoding passwords in %s\n", (recursing) ? "" : "\n", file);
- buf = mallocw (BUFSIZ);
- while (fgets (buf, BUFSIZ, fp) != NULLCHAR){
- rip (buf);
- len = (int) strlen (buf);
- if (len == 0)
- continue; /* Blank line */
-
- if (!strnicmp (buf, "#include", 8)) {
- cp = skipwhite (&buf[8]);
- usercvtfile (cp, 1);
- continue;
- }
- if (*buf == '#')
- continue; /* Comment line */
-
- if ((nlen = (int) strcspn (buf,Whitespace)) == len)
- continue; /* No end to the name! */
-
- /* Skip whitespace between name and pass */
- for (pass = &buf[nlen]; isspace (*pass); pass++)
- ;
- if(*pass != '\0' && *pass != '*'
- && readhex (hexbuf, pass, sizeof (hexbuf)) != 16){
- needsit = 1;
- break;
- }
- }
- if(!needsit){
- /* Everything is in order */
- (void) fclose (fp);
- free (buf);
- return;
- }
- /* At least one entry needs its password hashed */
- rewind (fp);
- fptmp = tmpfile();
- if (fptmp == NULLFILE) {
- printf ("Can't rewrite %s: can't create a tempfile!\n", file);
- (void) fclose (fp);
- free (buf);
- return;
- }
- while (fgets (buf, BUFSIZ, fp) != NULLCHAR) {
- rip (buf);
- if ((len = (int) strlen (buf)) == 0 || *buf == '#'
- || (nlen = (int) strcspn (buf, Whitespace)) == len){
- /* Line is blank, a comment or unparseable;
- * copy unchanged
- */
- fputs (buf, fptmp);
- fputc ('\n', fptmp);
- continue;
- }
- /* Skip whitespace between name and pass */
- for (pass = &buf[nlen]; isspace (*pass); pass++)
- ;
-
- if(*pass == '\0' || *pass == '*'
- || (plen = (int) strcspn (pass, Whitespace)) == (int)strlen (pass)
- || readhex (hexbuf, pass, sizeof (hexbuf)) == (int)sizeof (hexbuf)){
- /* Other fields are missing, no password is required,
- * or password is already hashed; copy unchanged
- */
- fputs (buf, fptmp);
- fputc ('\n', fptmp);
- continue;
- }
- MD5Init (&md);
- MD5Update (&md, (unsigned char *) buf, (unsigned int)nlen); /* Hash name */
- MD5Update (&md, (unsigned char *) pass, (unsigned int)plen); /* Hash password */
- MD5Final (&md);
- fwrite (buf, 1, (unsigned int)nlen, fptmp); /* Write name */
- fputc (' ', fptmp); /* and space */
- for (i = 0; i < 16; i++) /* Write hashed password */
- fprintf (fptmp, "%02x", md.digest[i] & 0xff);
- fputs (&pass[plen], fptmp); /* Write remainder of line */
- fputc ('\n', fptmp);
- }
- /* Now copy the temp file back into the userfile */
- (void) fclose (fp);
- rewind (fptmp);
- if ((fp = fopen (file, WRITE_TEXT)) == NULLFILE) {
- printf ("Can't rewrite %s\n", file);
- free (buf);
- return;
- }
- while (fgets (buf, BUFSIZ, fptmp) != NULLCHAR)
- fputs (buf, fp);
- (void) fclose (fp);
- (void) fclose (fptmp);
- free (buf);
- }
-
-
- /* MD5 hash plaintext passwords in user file */
- void
- usercvt()
- {
- usercvtfile (Userfile, 0);
- }
-
-
-
-